home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / Delphi 3.0 / DATA.Z / extctrls.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-01-29  |  60.5 KB  |  2,356 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,97 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ExtCtrls;
  11.  
  12. {$S-,W-,R-}
  13. {$C PRELOAD}
  14.  
  15. interface
  16.  
  17. uses Messages, Windows, SysUtils, Classes, Controls, Forms, Menus, Graphics,
  18.   StdCtrls;
  19.  
  20. type
  21.  
  22.   TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare,
  23.     stEllipse, stCircle);
  24.  
  25.   TShape = class(TGraphicControl)
  26.   private
  27.     FPen: TPen;
  28.     FBrush: TBrush;
  29.     FShape: TShapeType;
  30.     procedure SetBrush(Value: TBrush);
  31.     procedure SetPen(Value: TPen);
  32.     procedure SetShape(Value: TShapeType);
  33.   protected
  34.     procedure Paint; override;
  35.   public
  36.     constructor Create(AOwner: TComponent); override;
  37.     destructor Destroy; override;
  38.   published
  39.     procedure StyleChanged(Sender: TObject);
  40.     property Align;
  41.     property Brush: TBrush read FBrush write SetBrush;
  42.     property DragCursor;
  43.     property DragMode;
  44.     property Enabled;
  45.     property ParentShowHint;
  46.     property Pen: TPen read FPen write SetPen;
  47.     property Shape: TShapeType read FShape write SetShape default stRectangle;
  48.     property ShowHint;
  49.     property Visible;
  50.     property OnDragDrop;
  51.     property OnDragOver;
  52.     property OnEndDrag;
  53.     property OnMouseDown;
  54.     property OnMouseMove;
  55.     property OnMouseUp;
  56.     property OnStartDrag;
  57.   end;
  58.  
  59.   TPaintBox = class(TGraphicControl)
  60.   private
  61.     FOnPaint: TNotifyEvent;
  62.   protected
  63.     procedure Paint; override;
  64.   public
  65.     constructor Create(AOwner: TComponent); override;
  66.     property Canvas;
  67.   published
  68.     property Align;
  69.     property Color;
  70.     property DragCursor;
  71.     property DragMode;
  72.     property Enabled;
  73.     property Font;
  74.     property ParentColor;
  75.     property ParentFont;
  76.     property ParentShowHint;
  77.     property PopupMenu;
  78.     property ShowHint;
  79.     property Visible;
  80.     property OnClick;
  81.     property OnDblClick;
  82.     property OnDragDrop;
  83.     property OnDragOver;
  84.     property OnEndDrag;
  85.     property OnMouseDown;
  86.     property OnMouseMove;
  87.     property OnMouseUp;
  88.     property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  89.     property OnStartDrag;
  90.   end;
  91.  
  92.   TImage = class(TGraphicControl)
  93.   private
  94.     FPicture: TPicture;
  95.     FOnProgress: TProgressEvent;
  96.     FAutoSize: Boolean;
  97.     FStretch: Boolean;
  98.     FCenter: Boolean;
  99.     FIncrementalDisplay: Boolean;
  100.     function GetCanvas: TCanvas;
  101.     procedure PictureChanged(Sender: TObject);
  102.     procedure SetAutoSize(Value: Boolean);
  103.     procedure SetCenter(Value: Boolean);
  104.     procedure SetPicture(Value: TPicture);
  105.     procedure SetStretch(Value: Boolean);
  106.   protected
  107.     function DestRect: TRect;
  108.     function GetPalette: HPALETTE; override;
  109.     procedure Paint; override;
  110.     procedure Progress(Sender: TObject; Stage: TProgressStage;
  111.       PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string); dynamic;
  112.   public
  113.     constructor Create(AOwner: TComponent); override;
  114.     destructor Destroy; override;
  115.     property Canvas: TCanvas read GetCanvas;
  116.   published
  117.     property Align;
  118.     property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
  119.     property Center: Boolean read FCenter write SetCenter default False;
  120.     property DragCursor;
  121.     property DragMode;
  122.     property Enabled;
  123.     property IncrementalDisplay: Boolean read FIncrementalDisplay write FIncrementalDisplay;
  124.     property ParentShowHint;
  125.     property Picture: TPicture read FPicture write SetPicture;
  126.     property PopupMenu;
  127.     property ShowHint;
  128.     property Stretch: Boolean read FStretch write SetStretch default False;
  129.     property Visible;
  130.     property OnClick;
  131.     property OnDblClick;
  132.     property OnDragDrop;
  133.     property OnDragOver;
  134.     property OnEndDrag;
  135.     property OnMouseDown;
  136.     property OnMouseMove;
  137.     property OnMouseUp;
  138.     property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
  139.     property OnStartDrag;
  140.   end;
  141.  
  142.   TBevelStyle = (bsLowered, bsRaised);
  143.   TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine,
  144.     bsRightLine);
  145.  
  146.   TBevel = class(TGraphicControl)
  147.   private
  148.     FStyle: TBevelStyle;
  149.     FShape: TBevelShape;
  150.     procedure SetStyle(Value: TBevelStyle);
  151.     procedure SetShape(Value: TBevelShape);
  152.   protected
  153.     procedure Paint; override;
  154.   public
  155.     constructor Create(AOwner: TComponent); override;
  156.   published
  157.     property Align;
  158.     property ParentShowHint;
  159.     property Shape: TBevelShape read FShape write SetShape default bsBox;
  160.     property ShowHint;
  161.     property Style: TBevelStyle read FStyle write SetStyle default bsLowered;
  162.     property Visible;
  163.   end;
  164.  
  165.   TTimer = class(TComponent)
  166.   private
  167.     FInterval: Cardinal;
  168.     FWindowHandle: HWND;
  169.     FOnTimer: TNotifyEvent;
  170.     FEnabled: Boolean;
  171.     procedure UpdateTimer;
  172.     procedure SetEnabled(Value: Boolean);
  173.     procedure SetInterval(Value: Cardinal);
  174.     procedure SetOnTimer(Value: TNotifyEvent);
  175.     procedure WndProc(var Msg: TMessage);
  176.   protected
  177.     procedure Timer; dynamic;
  178.   public
  179.     constructor Create(AOwner: TComponent); override;
  180.     destructor Destroy; override;
  181.   published
  182.     property Enabled: Boolean read FEnabled write SetEnabled default True;
  183.     property Interval: Cardinal read FInterval write SetInterval default 1000;
  184.     property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  185.   end;
  186.  
  187.   TPanelBevel = (bvNone, bvLowered, bvRaised);
  188.   TBevelWidth = 1..MaxInt;
  189.   TBorderWidth = 0..MaxInt;
  190.  
  191.   TCustomPanel = class(TCustomControl)
  192.   private
  193.     FBevelInner: TPanelBevel;
  194.     FBevelOuter: TPanelBevel;
  195.     FBevelWidth: TBevelWidth;
  196.     FBorderWidth: TBorderWidth;
  197.     FBorderStyle: TBorderStyle;
  198.     FFullRepaint: Boolean;
  199.     FLocked: Boolean;
  200.     FOnResize: TNotifyEvent;
  201.     FAlignment: TAlignment;
  202.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  203.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  204.     procedure CMIsToolControl(var Message: TMessage); message CM_ISTOOLCONTROL;
  205.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  206.     procedure SetAlignment(Value: TAlignment);
  207.     procedure SetBevelInner(Value: TPanelBevel);
  208.     procedure SetBevelOuter(Value: TPanelBevel);
  209.     procedure SetBevelWidth(Value: TBevelWidth);
  210.     procedure SetBorderWidth(Value: TBorderWidth);
  211.     procedure SetBorderStyle(Value: TBorderStyle);
  212.   protected
  213.     procedure CreateParams(var Params: TCreateParams); override;
  214.     procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  215.     procedure Paint; override;
  216.     procedure Resize; dynamic;
  217.     property Alignment: TAlignment read FAlignment write SetAlignment default taCenter;
  218.     property BevelInner: TPanelBevel read FBevelInner write SetBevelInner default bvNone;
  219.     property BevelOuter: TPanelBevel read FBevelOuter write SetBevelOuter default bvRaised;
  220.     property BevelWidth: TBevelWidth read FBevelWidth write SetBevelWidth default 1;
  221.     property BorderWidth: TBorderWidth read FBorderWidth write SetBorderWidth default 0;
  222.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone;
  223.     property Color default clBtnFace;
  224.     property FullRepaint: Boolean read FFullRepaint write FFullRepaint default True;
  225.     property Locked: Boolean read FLocked write FLocked default False;
  226.     property ParentColor default False;
  227.     property OnResize: TNotifyEvent read FOnResize write FOnResize;
  228.   public
  229.     constructor Create(AOwner: TComponent); override;
  230.   end;
  231.  
  232.   TPanel = class(TCustomPanel)
  233.   published
  234.     property Align;
  235.     property Alignment;
  236.     property BevelInner;
  237.     property BevelOuter;
  238.     property BevelWidth;
  239.     property BorderWidth;
  240.     property BorderStyle;
  241.     property DragCursor;
  242.     property DragMode;
  243.     property Enabled;
  244.     property Caption;
  245.     property Color;
  246.     property Ctl3D;
  247.     property Font;
  248.     property Locked;
  249.     property ParentColor;
  250.     property ParentCtl3D;
  251.     property ParentFont;
  252.     property ParentShowHint;
  253.     property PopupMenu;
  254.     property ShowHint;
  255.     property TabOrder;
  256.     property TabStop;
  257.     property Visible;
  258.     property OnClick;
  259.     property OnDblClick;
  260.     property OnDragDrop;
  261.     property OnDragOver;
  262.     property OnEndDrag;
  263.     property OnEnter;
  264.     property OnExit;
  265.     property OnMouseDown;
  266.     property OnMouseMove;
  267.     property OnMouseUp;
  268.     property OnResize;
  269.     property OnStartDrag;
  270.   end;
  271.  
  272.   TPage = class(TCustomControl)
  273.   private
  274.     procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  275.   protected
  276.     procedure ReadState(Reader: TReader); override;
  277.     procedure Paint; override;
  278.   public
  279.     constructor Create(AOwner: TComponent); override;
  280.   published
  281.     property Caption;
  282.     property Height stored False;
  283.     property TabOrder stored False;
  284.     property Visible stored False;
  285.     property Width stored False;
  286.   end;
  287.  
  288.   TNotebook = class(TCustomControl)
  289.   private
  290.     FPageList: TList;
  291.     FAccess: TStrings;
  292.     FPageIndex: Integer;
  293.     FOnPageChanged: TNotifyEvent;
  294.     procedure SetPages(Value: TStrings);
  295.     procedure SetActivePage(const Value: string);
  296.     function GetActivePage: string;
  297.     procedure SetPageIndex(Value: Integer);
  298.   protected
  299.     procedure CreateParams(var Params: TCreateParams); override;
  300.     function GetChildOwner: TComponent; override;
  301.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  302.     procedure ReadState(Reader: TReader); override;
  303.     procedure ShowControl(AControl: TControl); override;
  304.   public
  305.     constructor Create(AOwner: TComponent); override;
  306.     destructor Destroy; override;
  307.   published
  308.     property ActivePage: string read GetActivePage write SetActivePage stored False;
  309.     property Align;
  310.     property Color;
  311.     property Ctl3D;
  312.     property DragCursor;
  313.     property DragMode;
  314.     property Font;
  315.     property Enabled;
  316.     property PageIndex: Integer read FPageIndex write SetPageIndex default 0;
  317.     property Pages: TStrings read FAccess write SetPages stored False;
  318.     property ParentColor;
  319.     property ParentCtl3D;
  320.     property ParentFont;
  321.     property ParentShowHint;
  322.     property PopupMenu;
  323.     property ShowHint;
  324.     property TabOrder;
  325.     property TabStop;
  326.     property Visible;
  327.     property OnClick;
  328.     property OnDblClick;
  329.     property OnDragDrop;
  330.     property OnDragOver;
  331.     property OnEndDrag;
  332.     property OnEnter;
  333.     property OnExit;
  334.     property OnMouseDown;
  335.     property OnMouseMove;
  336.     property OnMouseUp;
  337.     property OnPageChanged: TNotifyEvent read FOnPageChanged write FOnPageChanged;
  338.     property OnStartDrag;
  339.   end;
  340.  
  341. { THeader
  342.   Purpose  - Creates sectioned visual header that allows each section to be
  343.              resized with the mouse.
  344.   Features - This is a design-interactive control.  In design mode, the
  345.              sections are named using the string-list editor.  Each section
  346.              can now be manually resized using the right mouse button the grab
  347.              the divider and drag to the new size.  Changing the section list
  348.              at design (or even run-time), will attempt to maintain the
  349.              section widths for sections that have not been changed.
  350.   Properties:
  351.     Align - Standard property.
  352.     AllowResize - If True, the control allows run-time mouse resizing of the
  353.                   sections.
  354.     BorderStyle - Turns the border on and off.
  355.     Font - Standard property.
  356.     Sections - A special string-list that contains the section text.
  357.     ParentFont - Standard property.
  358.     OnSizing - Event called for each mouse move during a section resize
  359.                operation.
  360.     OnSized - Event called once the size operation is complete.
  361.  
  362.     SectionWidth - Array property allowing run-time getting and setting of
  363.                    each section's width. }
  364.  
  365.   TSectionEvent = procedure(Sender: TObject;
  366.     ASection, AWidth: Integer) of object;
  367.  
  368.   THeader = class(TCustomControl)
  369.   private
  370.     FSections: TStrings;
  371.     FHitTest: TPoint;
  372.     FCanResize: Boolean;
  373.     FAllowResize: Boolean;
  374.     FBorderStyle: TBorderStyle;
  375.     FResizeSection: Integer;
  376.     FMouseOffset: Integer;
  377.     FOnSizing: TSectionEvent;
  378.     FOnSized: TSectionEvent;
  379.     procedure SetBorderStyle(Value: TBorderStyle);
  380.     procedure FreeSections;
  381.     procedure SetSections(Strings: TStrings);
  382.     function GetWidth(X: Integer): Integer;
  383.     procedure SetWidth(X: Integer; Value: Integer);
  384.     procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  385.     procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
  386.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  387.       X, Y: Integer); override;
  388.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  389.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  390.       X, Y: Integer); override;
  391.   protected
  392.     procedure Paint; override;
  393.     procedure CreateParams(var Params: TCreateParams); override;
  394.     procedure Sizing(ASection, AWidth: Integer); dynamic;
  395.     procedure Sized(ASection, AWidth: Integer); dynamic;
  396.   public
  397.     constructor Create(AOwner: TComponent); override;
  398.     destructor Destroy; override;
  399.     property SectionWidth[X: Integer]: Integer read GetWidth write SetWidth;
  400.   published
  401.     property Align;
  402.     property AllowResize: Boolean read FAllowResize write FAllowResize default True;
  403.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
  404.     property Enabled;
  405.     property Font;
  406.     property ParentFont;
  407.     property ParentShowHint;
  408.     property PopupMenu;
  409.     property Sections: TStrings read FSections write SetSections;
  410.     property ShowHint;
  411.     property TabOrder;
  412.     property TabStop;
  413.     property Visible;
  414.     property OnSizing: TSectionEvent read FOnSizing write FOnSizing;
  415.     property OnSized: TSectionEvent read FOnSized write FOnSized;
  416.   end;
  417.  
  418.   TCustomRadioGroup = class(TCustomGroupBox)
  419.   private
  420.     FButtons: TList;
  421.     FItems: TStrings;
  422.     FItemIndex: Integer;
  423.     FColumns: Integer;
  424.     FReading: Boolean;
  425.     FUpdating: Boolean;
  426.     procedure ArrangeButtons;
  427.     procedure ButtonClick(Sender: TObject);
  428.     procedure ItemsChange(Sender: TObject);
  429.     procedure SetButtonCount(Value: Integer);
  430.     procedure SetColumns(Value: Integer);
  431.     procedure SetItemIndex(Value: Integer);
  432.     procedure SetItems(Value: TStrings);
  433.     procedure UpdateButtons;
  434.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  435.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  436.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  437.   protected
  438.     procedure ReadState(Reader: TReader); override;
  439.     function CanModify: Boolean; virtual;
  440.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  441.     property Columns: Integer read FColumns write SetColumns default 1;
  442.     property ItemIndex: Integer read FItemIndex write SetItemIndex default -1;
  443.     property Items: TStrings read FItems write SetItems;
  444.   public
  445.     constructor Create(AOwner: TComponent); override;
  446.     destructor Destroy; override;
  447.   end;
  448.  
  449.   TRadioGroup = class(TCustomRadioGroup)
  450.   published
  451.     property Align;
  452.     property Caption;
  453.     property Color;
  454.     property Columns;
  455.     property Ctl3D;
  456.     property DragCursor;
  457.     property DragMode;
  458.     property Enabled;
  459.     property Font;
  460.     property ItemIndex;
  461.     property Items;
  462.     property ParentColor;
  463.     property ParentCtl3D;
  464.     property ParentFont;
  465.     property ParentShowHint;
  466.     property PopupMenu;
  467.     property ShowHint;
  468.     property TabOrder;
  469.     property TabStop;
  470.     property Visible;
  471.     property OnClick;
  472.     property OnDragDrop;
  473.     property OnDragOver;
  474.     property OnEndDrag;
  475.     property OnEnter;
  476.     property OnExit;
  477.     property OnStartDrag;
  478.   end;
  479.  
  480.   NaturalNumber = 1..High(Integer);
  481.  
  482.   TSplitter = class(TGraphicControl)
  483.   private
  484.     FLineDC: HDC;
  485.     FDownPos: TPoint;
  486.     FSplit: Integer;
  487.     FMinSize: NaturalNumber;
  488.     FMaxSize: Integer;
  489.     FControl: TControl;
  490.     FNewSize: Integer;
  491.     FActiveControl: TWinControl;
  492.     FOldKeyDown: TKeyEvent;
  493.     FBeveled: Boolean;
  494.     FLineVisible: Boolean;
  495.     FOnMoved: TNotifyEvent;
  496.     procedure AllocateLineDC;
  497.     procedure DrawLine;
  498.     procedure ReleaseLineDC;
  499.     procedure UpdateSize(X, Y: Integer);
  500.     procedure FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  501.     procedure SetBeveled(Value: Boolean);
  502.   protected
  503.     procedure Paint; override;
  504.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  505.       X, Y: Integer); override;
  506.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  507.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  508.       X, Y: Integer); override;
  509.     procedure StopSizing;
  510.   public
  511.     constructor Create(AOwner: TComponent); override;
  512.   published
  513.     property Align default alLeft;
  514.     property Beveled: Boolean read FBeveled write SetBeveled default True;
  515.     property Color;
  516.     property MinSize: NaturalNumber read FMinSize write FMinSize default 30;
  517.     property ParentColor;
  518.     property OnMoved: TNotifyEvent read FOnMoved write FOnMoved;
  519.   end;
  520.  
  521. procedure Frame3D(Canvas: TCanvas; var Rect: TRect;
  522.   TopColor, BottomColor: TColor; Width: Integer);
  523.  
  524. implementation
  525.  
  526. uses Consts;
  527.  
  528. { Utility routines }
  529.  
  530. procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor;
  531.   Width: Integer);
  532.  
  533.   procedure DoRect;
  534.   var
  535.     TopRight, BottomLeft: TPoint;
  536.   begin
  537.     with Canvas, Rect do
  538.     begin
  539.       TopRight.X := Right;
  540.       TopRight.Y := Top;
  541.       BottomLeft.X := Left;
  542.       BottomLeft.Y := Bottom;
  543.       Pen.Color := TopColor;
  544.       PolyLine([BottomLeft, TopLeft, TopRight]);
  545.       Pen.Color := BottomColor;
  546.       Dec(BottomLeft.X);
  547.       PolyLine([TopRight, BottomRight, BottomLeft]);
  548.     end;
  549.   end;
  550.  
  551. begin
  552.   Canvas.Pen.Width := 1;
  553.   Dec(Rect.Bottom); Dec(Rect.Right);
  554.   while Width > 0 do
  555.   begin
  556.     Dec(Width);
  557.     DoRect;
  558.     InflateRect(Rect, -1, -1);
  559.   end;
  560.   Inc(Rect.Bottom); Inc(Rect.Right);
  561. end;
  562.  
  563. { TShape }
  564.  
  565. constructor TShape.Create(AOwner: TComponent);
  566. begin
  567.   inherited Create(AOwner);
  568.   ControlStyle := ControlStyle + [csReplicatable];
  569.   Width := 65;
  570.   Height := 65;
  571.   FPen := TPen.Create;
  572.   FPen.OnChange := StyleChanged;
  573.   FBrush := TBrush.Create;
  574.   FBrush.OnChange := StyleChanged;
  575. end;
  576.  
  577. destructor TShape.Destroy;
  578. begin
  579.   FPen.Free;
  580.   FBrush.Free;
  581.   inherited Destroy;
  582. end;
  583.  
  584. procedure TShape.Paint;
  585. var
  586.   X, Y, W, H, S: Integer;
  587. begin
  588.   with Canvas do
  589.   begin
  590.     Pen := FPen;
  591.     Brush := FBrush;
  592.     X := Pen.Width div 2;
  593.     Y := X;
  594.     W := Width - Pen.Width + 1;
  595.     H := Height - Pen.Width + 1;
  596.     if Pen.Width = 0 then
  597.     begin
  598.       Dec(W);
  599.       Dec(H);
  600.     end;
  601.     if W < H then S := W else S := H;
  602.     if FShape in [stSquare, stRoundSquare, stCircle] then
  603.     begin
  604.       Inc(X, (W - S) div 2);
  605.       Inc(Y, (H - S) div 2);
  606.       W := S;
  607.       H := S;
  608.     end;
  609.     case FShape of
  610.       stRectangle, stSquare:
  611.         Rectangle(X, Y, X + W, Y + H);
  612.       stRoundRect, stRoundSquare:
  613.         RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);
  614.       stCircle, stEllipse:
  615.         Ellipse(X, Y, X + W, Y + H);
  616.     end;
  617.   end;
  618. end;
  619.  
  620. procedure TShape.StyleChanged(Sender: TObject);
  621. begin
  622.   Invalidate;
  623. end;
  624.  
  625. procedure TShape.SetBrush(Value: TBrush);
  626. begin
  627.   FBrush.Assign(Value);
  628. end;
  629.  
  630. procedure TShape.SetPen(Value: TPen);
  631. begin
  632.   FPen.Assign(Value);
  633. end;
  634.  
  635. procedure TShape.SetShape(Value: TShapeType);
  636. begin
  637.   if FShape <> Value then
  638.   begin
  639.     FShape := Value;
  640.     Invalidate;
  641.   end;
  642. end;
  643.  
  644. { TPaintBox }
  645.  
  646. constructor TPaintBox.Create(AOwner: TComponent);
  647. begin
  648.   inherited Create(AOwner);
  649.   ControlStyle := ControlStyle + [csReplicatable];
  650.   Width := 105;
  651.   Height := 105;
  652. end;
  653.  
  654. procedure TPaintBox.Paint;
  655. begin
  656.   Canvas.Font := Font;
  657.   Canvas.Brush.Color := Color;
  658.   if csDesigning in ComponentState then
  659.     with Canvas do
  660.     begin
  661.       Pen.Style := psDash;
  662.       Brush.Style := bsClear;
  663.       Rectangle(0, 0, Width, Height);
  664.     end;
  665.   if Assigned(FOnPaint) then FOnPaint(Self);
  666. end;
  667.  
  668. { TImage }
  669.  
  670. constructor TImage.Create(AOwner: TComponent);
  671. begin
  672.   inherited Create(AOwner);
  673.   ControlStyle := ControlStyle + [csReplicatable];
  674.   FPicture := TPicture.Create;
  675.   FPicture.OnChange := PictureChanged;
  676.   FPicture.OnProgress := Progress;
  677.   Height := 105;
  678.   Width := 105;
  679. end;
  680.  
  681. destructor TImage.Destroy;
  682. begin
  683.   FPicture.Free;
  684.   inherited Destroy;
  685. end;
  686.  
  687. function TImage.GetPalette: HPALETTE;
  688. begin
  689.   Result := 0;
  690.   if FPicture.Graphic <> nil then
  691.     Result := FPicture.Graphic.Palette;
  692. end;
  693.  
  694. function TImage.DestRect: TRect;
  695. begin
  696.   if Stretch then
  697.     Result := ClientRect
  698.   else if Center then
  699.     Result := Bounds((Width - Picture.Width) div 2, (Height - Picture.Height) div 2,
  700.       Picture.Width, Picture.Height)
  701.   else
  702.     Result := Rect(0, 0, Picture.Width, Picture.Height);
  703. end;
  704.  
  705. procedure TImage.Paint;
  706. begin
  707.   if csDesigning in ComponentState then
  708.     with inherited Canvas do
  709.     begin
  710.       Pen.Style := psDash;
  711.       Brush.Style := bsClear;
  712.       Rectangle(0, 0, Width, Height);
  713.     end;
  714.   with inherited Canvas do
  715.     StretchDraw(DestRect, Picture.Graphic);
  716. end;
  717.  
  718. procedure TImage.Progress(Sender: TObject; Stage: TProgressStage;
  719.   PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string);
  720. begin
  721.   if FIncrementalDisplay and RedrawNow then Paint;
  722.   if Assigned(FOnProgress) then FOnProgress(Sender, Stage, PercentDone, RedrawNow, R, Msg);
  723. end;
  724.  
  725. function TImage.GetCanvas: TCanvas;
  726. var
  727.   Bitmap: TBitmap;
  728. begin
  729.   if Picture.Graphic = nil then
  730.   begin
  731.     Bitmap := TBitmap.Create;
  732.     try
  733.       Bitmap.Width := Width;
  734.       Bitmap.Height := Height;
  735.       Picture.Graphic := Bitmap;
  736.     finally
  737.       Bitmap.Free;
  738.     end;
  739.   end;
  740.   if Picture.Graphic is TBitmap then
  741.     Result := TBitmap(Picture.Graphic).Canvas
  742.   else
  743.     raise EInvalidOperation.Create(SImageCanvasNeedsBitmap);
  744. end;
  745.  
  746. procedure TImage.SetAutoSize(Value: Boolean);
  747. begin
  748.   FAutoSize := Value;
  749.   PictureChanged(Self);
  750. end;
  751.  
  752. procedure TImage.SetCenter(Value: Boolean);
  753. begin
  754.   if FCenter <> Value then
  755.   begin
  756.     FCenter := Value;
  757.     PictureChanged(Self);
  758.   end;
  759. end;
  760.  
  761. procedure TImage.SetPicture(Value: TPicture);
  762. begin
  763.   FPicture.Assign(Value);
  764. end;
  765.  
  766. procedure TImage.SetStretch(Value: Boolean);
  767. begin
  768.   if Value <> FStretch then
  769.   begin
  770.     FStretch := Value;
  771.     PictureChanged(Self);
  772.   end;
  773. end;
  774.  
  775. procedure TImage.PictureChanged(Sender: TObject);
  776. var
  777.   ParentForm: TCustomForm;
  778. begin
  779.   if AutoSize and (Picture.Width > 0) and (Picture.Height > 0) then
  780.     SetBounds(Left, Top, Picture.Width, Picture.Height);
  781.   if Picture.Graphic <> nil then
  782.   begin
  783.     if (not Picture.Graphic.Transparent) and (Picture.Width >= Width)
  784.       and (Picture.Height >= Height) then
  785.       ControlStyle := ControlStyle + [csOpaque]
  786.     else
  787.       ControlStyle := ControlStyle - [csOpaque];
  788.     if Visible and (not (csLoading in ComponentState)) and Picture.Graphic.PaletteModified then
  789.     begin
  790.       ParentForm := GetParentForm(Self);
  791.       if Assigned(ParentForm) and ParentForm.Active and Parentform.HandleAllocated then
  792.         PostMessage(ParentForm.Handle, wm_QueryNewPalette, 0, 0);
  793.       Picture.Graphic.PaletteModified := False;
  794.     end;
  795.   end
  796.   else ControlStyle := ControlStyle - [csOpaque];
  797.   Invalidate;
  798. end;
  799.  
  800. { TBevel }
  801.  
  802. constructor TBevel.Create(AOwner: TComponent);
  803. begin
  804.   inherited Create(AOwner);
  805.   ControlStyle := ControlStyle + [csReplicatable];
  806.   FStyle := bsLowered;
  807.   FShape := bsBox;
  808.   Width := 50;
  809.   Height := 50;
  810. end;
  811.  
  812. procedure TBevel.SetStyle(Value: TBevelStyle);
  813. begin
  814.   if Value <> FStyle then
  815.   begin
  816.     FStyle := Value;
  817.     Invalidate;
  818.   end;
  819. end;
  820.  
  821. procedure TBevel.SetShape(Value: TBevelShape);
  822. begin
  823.   if Value <> FShape then
  824.   begin
  825.     FShape := Value;
  826.     Invalidate;
  827.   end;
  828. end;
  829.  
  830. procedure TBevel.Paint;
  831. var
  832.   Color1, Color2: TColor;
  833.   Temp: TColor;
  834.  
  835.   procedure BevelRect(const R: TRect);
  836.   begin
  837.     with Canvas do
  838.     begin
  839.       Pen.Color := Color1;
  840.       PolyLine([Point(R.Left, R.Bottom), Point(R.Left, R.Top),
  841.         Point(R.Right, R.Top)]);
  842.       Pen.Color := Color2;
  843.       PolyLine([Point(R.Right, R.Top), Point(R.Right, R.Bottom),
  844.         Point(R.Left, R.Bottom)]);
  845.     end;
  846.   end;
  847.  
  848.   procedure BevelLine(C: TColor; X1, Y1, X2, Y2: Integer);
  849.   begin
  850.     with Canvas do
  851.     begin
  852.       Pen.Color := C;
  853.       MoveTo(X1, Y1);
  854.       LineTo(X2, Y2);
  855.     end;
  856.   end;
  857.  
  858. begin
  859.   with Canvas do
  860.   begin
  861.     Pen.Width := 1;
  862.  
  863.     if FStyle = bsLowered then
  864.     begin
  865.       Color1 := clBtnShadow;
  866.       Color2 := clBtnHighlight;
  867.     end
  868.     else
  869.     begin
  870.       Color1 := clBtnHighlight;
  871.       Color2 := clBtnShadow;
  872.     end;
  873.  
  874.     case FShape of
  875.       bsBox: BevelRect(Rect(0, 0, Width - 1, Height - 1));
  876.       bsFrame:
  877.         begin
  878.           Temp := Color1;
  879.           Color1 := Color2;
  880.           BevelRect(Rect(1, 1, Width - 1, Height - 1));
  881.           Color2 := Temp;
  882.           Color1 := Temp;
  883.           BevelRect(Rect(0, 0, Width - 2, Height - 2));
  884.         end;
  885.       bsTopLine:
  886.         begin
  887.           BevelLine(Color1, 0, 0, Width, 0);
  888.           BevelLine(Color2, 0, 1, Width, 1);
  889.         end;
  890.       bsBottomLine:
  891.         begin
  892.           BevelLine(Color1, 0, Height - 2, Width, Height - 2);
  893.           BevelLine(Color2, 0, Height - 1, Width, Height - 1);
  894.         end;
  895.       bsLeftLine:
  896.         begin
  897.           BevelLine(Color1, 0, 0, 0, Height);
  898.           BevelLine(Color2, 1, 0, 1, Height);
  899.         end;
  900.       bsRightLine:
  901.         begin
  902.           BevelLine(Color1, Width - 2, 0, Width - 2, Height);
  903.           BevelLine(Color2, Width - 1, 0, Width - 1, Height);
  904.         end;
  905.     end;
  906.   end;
  907. end;
  908.  
  909. { TTimer }
  910.  
  911. constructor TTimer.Create(AOwner: TComponent);
  912. begin
  913.   inherited Create(AOwner);
  914.   FEnabled := True;
  915.   FInterval := 1000;
  916.   FWindowHandle := AllocateHWnd(WndProc);
  917. end;
  918.  
  919. destructor TTimer.Destroy;
  920. begin
  921.   FEnabled := False;
  922.   UpdateTimer;
  923.   DeallocateHWnd(FWindowHandle);
  924.   inherited Destroy;
  925. end;
  926.  
  927. procedure TTimer.WndProc(var Msg: TMessage);
  928. begin
  929.   with Msg do
  930.     if Msg = WM_TIMER then
  931.       try
  932.         Timer;
  933.       except
  934.         Application.HandleException(Self);
  935.       end
  936.     else
  937.       Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  938. end;
  939.  
  940. procedure TTimer.UpdateTimer;
  941. begin
  942.   KillTimer(FWindowHandle, 1);
  943.   if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  944.     if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
  945.       raise EOutOfResources.Create(SNoTimers);
  946. end;
  947.  
  948. procedure TTimer.SetEnabled(Value: Boolean);
  949. begin
  950.   if Value <> FEnabled then
  951.   begin
  952.     FEnabled := Value;
  953.     UpdateTimer;
  954.   end;
  955. end;
  956.  
  957. procedure TTimer.SetInterval(Value: Cardinal);
  958. begin
  959.   if Value <> FInterval then
  960.   begin
  961.     FInterval := Value;
  962.     UpdateTimer;
  963.   end;
  964. end;
  965.  
  966. procedure TTimer.SetOnTimer(Value: TNotifyEvent);
  967. begin
  968.   FOnTimer := Value;
  969.   UpdateTimer;
  970. end;
  971.  
  972. procedure TTimer.Timer;
  973. begin
  974.   if Assigned(FOnTimer) then FOnTimer(Self);
  975. end;
  976.  
  977. { TCustomPanel }
  978.  
  979. constructor TCustomPanel.Create(AOwner: TComponent);
  980. begin
  981.   inherited Create(AOwner);
  982.   ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
  983.     csSetCaption, csOpaque, csDoubleClicks, csReplicatable];
  984.   Width := 185;
  985.   Height := 41;
  986.   FAlignment := taCenter;
  987.   BevelOuter := bvRaised;
  988.   BevelWidth := 1;
  989.   FBorderStyle := bsNone;
  990.   Color := clBtnFace;
  991.   FFullRepaint := True;
  992. end;
  993.  
  994. procedure TCustomPanel.CreateParams(var Params: TCreateParams);
  995. const
  996.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  997. begin
  998.   inherited CreateParams(Params);
  999.   with Params do
  1000.   begin
  1001.     Style := Style or BorderStyles[FBorderStyle];
  1002.     if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then
  1003.     begin
  1004.       Style := Style and not WS_BORDER;
  1005.       ExStyle := ExStyle or WS_EX_CLIENTEDGE;
  1006.     end;
  1007.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  1008.   end;
  1009. end;
  1010.  
  1011. procedure TCustomPanel.CMTextChanged(var Message: TMessage);
  1012. begin
  1013.   Invalidate;
  1014. end;
  1015.  
  1016. procedure TCustomPanel.CMCtl3DChanged(var Message: TMessage);
  1017. begin
  1018.   if NewStyleControls and (FBorderStyle = bsSingle) then RecreateWnd;
  1019.   inherited;
  1020. end;
  1021.  
  1022. procedure TCustomPanel.CMIsToolControl(var Message: TMessage);
  1023. begin
  1024.   if not FLocked then Message.Result := 1;
  1025. end;
  1026.  
  1027. procedure TCustomPanel.Resize;
  1028. begin
  1029.   if FullRepaint then Invalidate;
  1030.   if Assigned(FOnResize) then FOnResize(Self);
  1031. end;
  1032.  
  1033. procedure TCustomPanel.WMSize(var Message: TWMSize);
  1034. begin
  1035.   inherited;
  1036.   if not (csLoading in ComponentState) then Resize;
  1037. end;
  1038.  
  1039. procedure TCustomPanel.AlignControls(AControl: TControl; var Rect: TRect);
  1040. var
  1041.   BevelSize: Integer;
  1042. begin
  1043.   BevelSize := BorderWidth;
  1044.   if BevelOuter <> bvNone then Inc(BevelSize, BevelWidth);
  1045.   if BevelInner <> bvNone then Inc(BevelSize, BevelWidth);
  1046.   InflateRect(Rect, -BevelSize, -BevelSize);
  1047.   inherited AlignControls(AControl, Rect);
  1048. end;
  1049.  
  1050. procedure TCustomPanel.Paint;
  1051. var
  1052.   Rect: TRect;
  1053.   TopColor, BottomColor: TColor;
  1054.   FontHeight: Integer;
  1055. const
  1056.   Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
  1057.  
  1058.   procedure AdjustColors(Bevel: TPanelBevel);
  1059.   begin
  1060.     TopColor := clBtnHighlight;
  1061.     if Bevel = bvLowered then TopColor := clBtnShadow;
  1062.     BottomColor := clBtnShadow;
  1063.     if Bevel = bvLowered then BottomColor := clBtnHighlight;
  1064.   end;
  1065.  
  1066. begin
  1067.   Rect := GetClientRect;
  1068.   if BevelOuter <> bvNone then
  1069.   begin
  1070.     AdjustColors(BevelOuter);
  1071.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  1072.   end;
  1073.   Frame3D(Canvas, Rect, Color, Color, BorderWidth);
  1074.   if BevelInner <> bvNone then
  1075.   begin
  1076.     AdjustColors(BevelInner);
  1077.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  1078.   end;
  1079.   with Canvas do
  1080.   begin
  1081.     Brush.Color := Color;
  1082.     FillRect(Rect);
  1083.     Brush.Style := bsClear;
  1084.     Font := Self.Font;
  1085.     FontHeight := TextHeight('W');
  1086.     with Rect do
  1087.     begin
  1088.       Top := ((Bottom + Top) - FontHeight) div 2;
  1089.       Bottom := Top + FontHeight;
  1090.     end;
  1091.     DrawText(Handle, PChar(Caption), -1, Rect, (DT_EXPANDTABS or
  1092.       DT_VCENTER) or Alignments[FAlignment]);
  1093.   end;
  1094. end;
  1095.  
  1096. procedure TCustomPanel.SetAlignment(Value: TAlignment);
  1097. begin
  1098.   FAlignment := Value;
  1099.   Invalidate;
  1100. end;
  1101.  
  1102. procedure TCustomPanel.SetBevelInner(Value: TPanelBevel);
  1103. begin
  1104.   FBevelInner := Value;
  1105.   Realign;
  1106.   Invalidate;
  1107. end;
  1108.  
  1109. procedure TCustomPanel.SetBevelOuter(Value: TPanelBevel);
  1110. begin
  1111.   FBevelOuter := Value;
  1112.   Realign;
  1113.   Invalidate;
  1114. end;
  1115.  
  1116. procedure TCustomPanel.SetBevelWidth(Value: TBevelWidth);
  1117. begin
  1118.   FBevelWidth := Value;
  1119.   Realign;
  1120.   Invalidate;
  1121. end;
  1122.  
  1123. procedure TCustomPanel.SetBorderWidth(Value: TBorderWidth);
  1124. begin
  1125.   FBorderWidth := Value;
  1126.   Realign;
  1127.   Invalidate;
  1128. end;
  1129.  
  1130. procedure TCustomPanel.SetBorderStyle(Value: TBorderStyle);
  1131. begin
  1132.   if FBorderStyle <> Value then
  1133.   begin
  1134.     FBorderStyle := Value;
  1135.     RecreateWnd;
  1136.   end;
  1137. end;
  1138.  
  1139. { TPageAccess }
  1140.  
  1141. type
  1142.   TPageAccess = class(TStrings)
  1143.   private
  1144.     PageList: TList;
  1145.     Notebook: TNotebook;
  1146.   protected
  1147.     function GetCount: Integer; override;
  1148.     function Get(Index: Integer): string; override;
  1149.     procedure Put(Index: Integer; const S: string); override;
  1150.     function GetObject(Index: Integer): TObject; override;
  1151.     procedure SetUpdateState(Updating: Boolean); override;
  1152.   public
  1153.     constructor Create(APageList: TList; ANotebook: TNotebook);
  1154.     procedure Clear; override;
  1155.     procedure Delete(Index: Integer); override;
  1156.     procedure Insert(Index: Integer; const S: string); override;
  1157.     procedure Move(CurIndex, NewIndex: Integer); override;
  1158.   end;
  1159.  
  1160. constructor TPageAccess.Create(APageList: TList; ANotebook: TNotebook);
  1161. begin
  1162.   inherited Create;
  1163.   PageList := APageList;
  1164.   Notebook := ANotebook;
  1165. end;
  1166.  
  1167. function TPageAccess.GetCount: Integer;
  1168. begin
  1169.   Result := PageList.Count;
  1170. end;
  1171.  
  1172. function TPageAccess.Get(Index: Integer): string;
  1173. begin
  1174.   Result := TPage(PageList[Index]).Caption;
  1175. end;
  1176.  
  1177. procedure TPageAccess.Put(Index: Integer; const S: string);
  1178. begin
  1179.   TPage(PageList[Index]).Caption := S;
  1180. end;
  1181.  
  1182. function TPageAccess.GetObject(Index: Integer): TObject;
  1183. begin
  1184.   Result := PageList[Index];
  1185. end;
  1186.  
  1187. procedure TPageAccess.SetUpdateState(Updating: Boolean);
  1188. begin
  1189.   { do nothing }
  1190. end;
  1191.  
  1192. procedure TPageAccess.Clear;
  1193. var
  1194.   I: Integer;
  1195. begin
  1196.   for I := 0 to PageList.Count - 1 do
  1197.     TPage(PageList[I]).Free;
  1198.   PageList.Clear;
  1199. end;
  1200.  
  1201. procedure TPageAccess.Delete(Index: Integer);
  1202. var
  1203.   Form: TCustomForm;
  1204. begin
  1205.   TPage(PageList[Index]).Free;
  1206.   PageList.Delete(Index);
  1207.   NoteBook.PageIndex := 0;
  1208.  
  1209.   if csDesigning in NoteBook.ComponentState then
  1210.   begin
  1211.     Form := GetParentForm(NoteBook);
  1212.     if (Form <> nil) and (Form.Designer <> nil) then
  1213.       Form.Designer.Modified;
  1214.   end;
  1215. end;
  1216.  
  1217. procedure TPageAccess.Insert(Index: Integer; const S: string);
  1218. var
  1219.   Page: TPage;
  1220.   Form: TCustomForm;
  1221. begin
  1222.   Page := TPage.Create(Notebook);
  1223.   with Page do
  1224.   begin
  1225.     Parent := Notebook;
  1226.     Caption := S;
  1227.   end;
  1228.   PageList.Insert(Index, Page);
  1229.  
  1230.   NoteBook.PageIndex := Index;
  1231.  
  1232.   if csDesigning in NoteBook.ComponentState then
  1233.   begin
  1234.     Form := GetParentForm(NoteBook);
  1235.     if (Form <> nil) and (Form.Designer <> nil) then
  1236.       Form.Designer.Modified;
  1237.   end;
  1238. end;
  1239.  
  1240. procedure TPageAccess.Move(CurIndex, NewIndex: Integer);
  1241. var
  1242.   AObject: TObject;
  1243. begin
  1244.   if CurIndex <> NewIndex then
  1245.   begin
  1246.     AObject := PageList[CurIndex];
  1247.     PageList[CurIndex] := PageList[NewIndex];
  1248.     PageList[NewIndex] := AObject;
  1249.   end;
  1250. end;
  1251.  
  1252. { TPage }
  1253.  
  1254. constructor TPage.Create(AOwner: TComponent);
  1255. begin
  1256.   inherited Create(AOwner);
  1257.   Visible := False;
  1258.   ControlStyle := ControlStyle + [csAcceptsControls];
  1259.   Align := alClient;
  1260. end;
  1261.  
  1262. procedure TPage.Paint;
  1263. begin
  1264.   inherited Paint;
  1265.   if csDesigning in ComponentState then
  1266.     with Canvas do
  1267.     begin
  1268.       Pen.Style := psDash;
  1269.       Brush.Style := bsClear;
  1270.       Rectangle(0, 0, Width, Height);
  1271.     end;
  1272. end;
  1273.  
  1274. procedure TPage.ReadState(Reader: TReader);
  1275. begin
  1276.   if Reader.Parent is TNotebook then
  1277.     TNotebook(Reader.Parent).FPageList.Add(Self);
  1278.   inherited ReadState(Reader);
  1279. end;
  1280.  
  1281. procedure TPage.WMNCHitTest(var Message: TWMNCHitTest);
  1282. begin
  1283.   if not (csDesigning in ComponentState) then
  1284.     Message.Result := HTTRANSPARENT
  1285.   else
  1286.     inherited;
  1287. end;
  1288.  
  1289. { TNotebook }
  1290.  
  1291. var
  1292.   Registered: Boolean = False;
  1293.  
  1294. constructor TNotebook.Create(AOwner: TComponent);
  1295. begin
  1296.   inherited Create(AOwner);
  1297.   Width := 150;
  1298.   Height := 150;
  1299.   FPageList := TList.Create;
  1300.   FAccess := TPageAccess.Create(FPageList, Self);
  1301.   FPageIndex := -1;
  1302.   FAccess.Add(SDefault);
  1303.   PageIndex := 0;
  1304.   Exclude(FComponentStyle, csInheritable);
  1305.   if not Registered then
  1306.   begin
  1307.     Classes.RegisterClasses([TPage]);
  1308.     Registered := True;
  1309.   end;
  1310. end;
  1311.  
  1312. destructor TNotebook.Destroy;
  1313. begin
  1314.   FAccess.Free;
  1315.   FPageList.Free;
  1316.   inherited Destroy;
  1317. end;
  1318.  
  1319. procedure TNotebook.CreateParams(var Params: TCreateParams);
  1320. begin
  1321.   inherited CreateParams(Params);
  1322.   with Params do
  1323.   begin
  1324.     Style := Style or WS_CLIPCHILDREN;
  1325.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  1326.   end;
  1327. end;
  1328.  
  1329. function TNotebook.GetChildOwner: TComponent;
  1330. begin
  1331.   Result := Self;
  1332. end;
  1333.  
  1334. procedure TNotebook.GetChildren(Proc: TGetChildProc; Root: TComponent);
  1335. var
  1336.   I: Integer;
  1337. begin
  1338.   for I := 0 to FPageList.Count - 1 do Proc(TControl(FPageList[I]));
  1339. end;
  1340.  
  1341. procedure TNotebook.ReadState(Reader: TReader);
  1342. begin
  1343.   Pages.Clear;
  1344.   inherited ReadState(Reader);
  1345.   if (FPageIndex <> -1) and (FPageIndex >= 0) and (FPageIndex < FPageList.Count) then
  1346.     with TPage(FPageList[FPageIndex]) do
  1347.     begin
  1348.       BringToFront;
  1349.       Visible := True;
  1350.       Align := alClient;
  1351.     end
  1352.   else FPageIndex := -1;
  1353. end;
  1354.  
  1355. procedure TNotebook.ShowControl(AControl: TControl);
  1356. var
  1357.   I: Integer;
  1358. begin
  1359.   for I := 0 to FPageList.Count - 1 do
  1360.     if FPageList[I] = AControl then
  1361.     begin
  1362.       SetPageIndex(I);
  1363.       Exit;
  1364.     end;
  1365.   inherited ShowControl(AControl);
  1366. end;
  1367.  
  1368. procedure TNotebook.SetPages(Value: TStrings);
  1369. begin
  1370.   FAccess.Assign(Value);
  1371. end;
  1372.  
  1373. procedure TNotebook.SetPageIndex(Value: Integer);
  1374. var
  1375.   ParentForm: TCustomForm;
  1376. begin
  1377.   if csLoading in ComponentState then
  1378.   begin
  1379.     FPageIndex := Value;
  1380.     Exit;
  1381.   end;
  1382.   if (Value <> FPageIndex) and (Value >= 0) and (Value < FPageList.Count) then
  1383.   begin
  1384.     ParentForm := GetParentForm(Self);
  1385.     if ParentForm <> nil then
  1386.       if ContainsControl(ParentForm.ActiveControl) then
  1387.         ParentForm.ActiveControl := Self;
  1388.     with TPage(FPageList[Value]) do
  1389.     begin
  1390.       BringToFront;
  1391.       Visible := True;
  1392.       Align := alClient;
  1393.     end;
  1394.     if (FPageIndex >= 0) and (FPageIndex < FPageList.Count) then
  1395.       TPage(FPageList[FPageIndex]).Visible := False;
  1396.     FPageIndex := Value;
  1397.     if ParentForm <> nil then
  1398.       if ParentForm.ActiveControl = Self then SelectFirst;
  1399.     if Assigned(FOnPageChanged) then
  1400.       FOnPageChanged(Self);
  1401.   end;
  1402. end;
  1403.  
  1404. procedure TNotebook.SetActivePage(const Value: string);
  1405. begin
  1406.   SetPageIndex(FAccess.IndexOf(Value));
  1407. end;
  1408.  
  1409. function TNotebook.GetActivePage: string;
  1410. begin
  1411.   Result := FAccess[FPageIndex];
  1412. end;
  1413.  
  1414. { THeaderStrings }
  1415.  
  1416. const
  1417.   DefaultSectionWidth = 75;
  1418.  
  1419. type
  1420.   PHeaderSection = ^THeaderSection;
  1421.   THeaderSection = record
  1422.     FObject: TObject;
  1423.     Width: Integer;
  1424.     Title: string;
  1425.   end;
  1426.  
  1427. type
  1428.   THeaderStrings = class(TStrings)
  1429.   private
  1430.     FHeader: THeader;
  1431.     FList: TList;
  1432.     procedure ReadData(Reader: TReader);
  1433.     procedure WriteData(Writer: TWriter);
  1434.   protected
  1435.     procedure DefineProperties(Filer: TFiler); override;
  1436.     function Get(Index: Integer): string; override;
  1437.     function GetCount: Integer; override;
  1438.     function GetObject(Index: Integer): TObject; override;
  1439.     procedure Put(Index: Integer; const S: string); override;
  1440.     procedure PutObject(Index: Integer; AObject: TObject); override;
  1441.     procedure SetUpdateState(Updating: Boolean); override;
  1442.   public
  1443.     constructor Create;
  1444.     destructor Destroy; override;
  1445.     procedure Assign(Source: TPersistent); override;
  1446.     procedure Delete(Index: Integer); override;
  1447.     procedure Insert(Index: Integer; const S: string); override;
  1448.     procedure Clear; override;
  1449.   end;
  1450.  
  1451. procedure FreeSection(Section: PHeaderSection);
  1452. begin
  1453.   if Section <> nil then Dispose(Section);
  1454. end;
  1455.  
  1456. function NewSection(const ATitle: string; AWidth: Integer; AObject: TObject): PHeaderSection;
  1457. begin
  1458.   New(Result);
  1459.   with Result^ do
  1460.   begin
  1461.     Title := ATitle;
  1462.     Width := AWidth;
  1463.     FObject := AObject;
  1464.   end;
  1465. end;
  1466.  
  1467. constructor THeaderStrings.Create;
  1468. begin
  1469.   inherited Create;
  1470.   FList := TList.Create;
  1471. end;
  1472.  
  1473. destructor THeaderStrings.Destroy;
  1474. begin
  1475.   if FList <> nil then
  1476.   begin
  1477.     Clear;
  1478.     FList.Destroy;
  1479.   end;
  1480.   inherited Destroy;
  1481. end;
  1482.  
  1483. procedure THeaderStrings.Assign(Source: TPersistent);
  1484. var
  1485.   I, J: Integer;
  1486.   Strings: TStrings;
  1487.   NewList: TList;
  1488.   Section: PHeaderSection;
  1489.   TempStr: string;
  1490.   Found: Boolean;
  1491. begin
  1492.   if Source is TStrings then
  1493.   begin
  1494.     Strings := TStrings(Source);
  1495.     BeginUpdate;
  1496.     try
  1497.       NewList := TList.Create;
  1498.       try
  1499.         { Delete any sections not in the new list }
  1500.         I := FList.Count - 1;
  1501.         Found := False;
  1502.         while I >= 0 do
  1503.         begin
  1504.           TempStr := Get(I);
  1505.           for J := 0 to Strings.Count - 1 do
  1506.           begin
  1507.             Found := CompareStr(Strings[J], TempStr) = 0;
  1508.             if Found then Break;
  1509.           end;
  1510.           if not Found then Delete(I);
  1511.           Dec(I);
  1512.         end;
  1513.  
  1514.         { Now iterate over the lists and maintain section widths of sections in
  1515.           the new list }
  1516.         I := 0;
  1517.         for J := 0 to Strings.Count - 1 do
  1518.         begin
  1519.           if (I < FList.Count) and (CompareStr(Strings[J], Get(I)) = 0) then
  1520.           begin
  1521.             Section := NewSection(Get(I), PHeaderSection(FList[I])^.Width, GetObject(I));
  1522.             Inc(I);
  1523.           end else
  1524.             Section := NewSection(Strings[J],
  1525.               FHeader.Canvas.TextWidth(Strings[J]) + 8, Strings.Objects[J]);
  1526.           NewList.Add(Section);
  1527.         end;
  1528.         Clear;
  1529.         FList.Destroy;
  1530.         FList := NewList;
  1531.         FHeader.Invalidate;
  1532.       except
  1533.         for I := 0 to NewList.Count - 1 do
  1534.           FreeSection(NewList[I]);
  1535.         NewList.Destroy;
  1536.         raise;
  1537.       end;
  1538.     finally
  1539.       EndUpdate;
  1540.     end;
  1541.     Exit;
  1542.   end;
  1543.   inherited Assign(Source);
  1544. end;
  1545.  
  1546. procedure THeaderStrings.DefineProperties(Filer: TFiler);
  1547. begin
  1548.   { This will allow the old file image read in }
  1549.   if Filer is TReader then inherited DefineProperties(Filer);
  1550.   Filer.DefineProperty('Sections', ReadData, WriteData, Count > 0);
  1551. end;
  1552.  
  1553. procedure THeaderStrings.Clear;
  1554. var
  1555.   I: Integer;
  1556. begin
  1557.   for I := 0 to FList.Count - 1 do
  1558.     FreeSection(FList[I]);
  1559.   FList.Clear;
  1560. end;
  1561.  
  1562. procedure THeaderStrings.Delete(Index: Integer);
  1563. begin
  1564.   FreeSection(FList[Index]);
  1565.   FList.Delete(Index);
  1566.   if FHeader <> nil then FHeader.Invalidate;
  1567. end;
  1568.  
  1569. function THeaderStrings.Get(Index: Integer): string;
  1570. begin
  1571.   Result := PHeaderSection(FList[Index])^.Title;
  1572. end;
  1573.  
  1574. function THeaderStrings.GetCount: Integer;
  1575. begin
  1576.   Result := FList.Count;
  1577. end;
  1578.  
  1579. function THeaderStrings.GetObject(Index: Integer): TObject;
  1580. begin
  1581.   Result := PHeaderSection(FList[Index])^.FObject;
  1582. end;
  1583.  
  1584. procedure THeaderStrings.Insert(Index: Integer; const S: string);
  1585. var
  1586.   Width: Integer;
  1587. begin
  1588.   if FHeader <> nil then
  1589.     Width := FHeader.Canvas.TextWidth(S) + 8
  1590.   else Width := DefaultSectionWidth;
  1591.   FList.Expand.Insert(Index, NewSection(S, Width, nil));
  1592.   if FHeader <> nil then FHeader.Invalidate;
  1593. end;
  1594.  
  1595. procedure THeaderStrings.Put(Index: Integer; const S: string);
  1596. var
  1597.   P: PHeaderSection;
  1598.   Width: Integer;
  1599. begin
  1600.   P := FList[Index];
  1601.   if FHeader <> nil then
  1602.     Width := FHeader.Canvas.TextWidth(S) + 8
  1603.   else Width := DefaultSectionWidth;
  1604.   FList[Index] := NewSection(S, Width, P^.FObject);
  1605.   FreeSection(P);
  1606.   if FHeader <> nil then FHeader.Invalidate;
  1607. end;
  1608.  
  1609. procedure THeaderStrings.PutObject(Index: Integer; AObject: TObject);
  1610. begin
  1611.   PHeaderSection(FList[Index])^.FObject := AObject;
  1612.   if FHeader <> nil then FHeader.Invalidate;
  1613. end;
  1614.  
  1615. procedure THeaderStrings.ReadData(Reader: TReader);
  1616. var
  1617.   Width, I: Integer;
  1618.   Str: string;
  1619. begin
  1620.   Reader.ReadListBegin;
  1621.   Clear;
  1622.   while not Reader.EndOfList do
  1623.   begin
  1624.     Str := Reader.ReadString;
  1625.     Width := DefaultSectionWidth;
  1626.     I := 1;
  1627.     if Str[1] = #0 then
  1628.     begin
  1629.       repeat
  1630.         Inc(I);
  1631.       until (I > Length(Str)) or (Str[I] = #0);
  1632.       Width := StrToIntDef(Copy(Str, 2, I - 2), DefaultSectionWidth);
  1633.       System.Delete(Str, 1, I);
  1634.     end;
  1635.     FList.Expand.Insert(FList.Count, NewSection(Str, Width, nil));
  1636.   end;
  1637.   Reader.ReadListEnd;
  1638. end;
  1639.  
  1640. procedure THeaderStrings.SetUpdateState(Updating: Boolean);
  1641. begin
  1642.   if FHeader <> nil then
  1643.   begin
  1644.     SendMessage(FHeader.Handle, WM_SETREDRAW, Ord(not Updating), 0);
  1645.     if not Updating then FHeader.Refresh;
  1646.   end;
  1647. end;
  1648.  
  1649. procedure THeaderStrings.WriteData(Writer: TWriter);
  1650. var
  1651.   I: Integer;
  1652.   HeaderSection: PHeaderSection;
  1653. begin
  1654.   Writer.WriteListBegin;
  1655.   for I := 0 to Count - 1 do
  1656.   begin
  1657.     HeaderSection := FList[I];
  1658.     with HeaderSection^ do
  1659.       Writer.WriteString(Format(#0'%d'#0'%s', [Width, Title]));
  1660.   end;
  1661.   Writer.WriteListEnd;
  1662. end;
  1663.  
  1664. { THeader }
  1665.  
  1666. constructor THeader.Create(AOwner: TComponent);
  1667. begin
  1668.   inherited Create(AOwner);
  1669.   ControlStyle := ControlStyle + [csDesignInteractive, csOpaque];
  1670.   Width := 250;
  1671.   Height := 25;
  1672.   FSections := THeaderStrings.Create;
  1673.   THeaderStrings(FSections).FHeader := Self;
  1674.   FAllowResize := True;
  1675.   FBorderStyle := bsSingle;
  1676. end;
  1677.  
  1678. destructor THeader.Destroy;
  1679. begin
  1680.   FreeSections;
  1681.   FSections.Free;
  1682.   inherited Destroy;
  1683. end;
  1684.  
  1685. procedure THeader.CreateParams(var Params: TCreateParams);
  1686. const
  1687.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  1688. begin
  1689.   inherited CreateParams(Params);
  1690.   with Params do
  1691.   begin
  1692.     Style := Style or BorderStyles[FBorderStyle];
  1693.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  1694.   end;
  1695. end;
  1696.  
  1697. procedure THeader.Paint;
  1698. var
  1699.   I, Y, W: Integer;
  1700.   S: string;
  1701.   R: TRect;
  1702. begin
  1703.   with Canvas do
  1704.   begin
  1705.     Font := Self.Font;
  1706.     Brush.Color := clBtnFace;
  1707.     I := 0;
  1708.     Y := (ClientHeight - Canvas.TextHeight('T')) div 2;
  1709.     R := Rect(0, 0, 0, ClientHeight);
  1710.     W := 0;
  1711.     S := '';
  1712.     repeat
  1713.       if I < FSections.Count then
  1714.       begin
  1715.         with PHeaderSection(THeaderStrings(FSections).FList[I])^ do
  1716.         begin
  1717.           W := Width;
  1718.           S := Title;
  1719.         end;
  1720.         Inc(I);
  1721.       end;
  1722.       R.Left := R.Right;
  1723.       Inc(R.Right, W);
  1724.       if (ClientWidth - R.Right < 2) or (I = FSections.Count) then
  1725.         R.Right := ClientWidth;
  1726.       TextRect(Rect(R.Left + 1, R.Top + 1, R.Right - 1, R.Bottom - 1),
  1727.         R.Left + 3, Y, S);
  1728.       DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_TOPLEFT);
  1729.       DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_BOTTOMRight);
  1730.     until R.Right = ClientWidth;
  1731.   end;
  1732. end;
  1733.  
  1734. procedure THeader.FreeSections;
  1735. begin
  1736.   if FSections <> nil then
  1737.     FSections.Clear;
  1738. end;
  1739.  
  1740. procedure THeader.SetBorderStyle(Value: TBorderStyle);
  1741. begin
  1742.   if Value <> FBorderStyle then
  1743.   begin
  1744.     FBorderStyle := Value;
  1745.     RecreateWnd;
  1746.   end;
  1747. end;
  1748.  
  1749. procedure THeader.SetSections(Strings: TStrings);
  1750. begin
  1751.   FSections.Assign(Strings);
  1752. end;
  1753.  
  1754. function THeader.GetWidth(X: Integer): Integer;
  1755. var
  1756.   I, W: Integer;
  1757. begin
  1758.   if X = FSections.Count - 1 then
  1759.   begin
  1760.     W := 0;
  1761.     for I := 0 to X - 1 do
  1762.       Inc(W, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1763.     Result := ClientWidth - W;
  1764.   end
  1765.   else if (X >= 0) and (X < FSections.Count) then
  1766.     Result := PHeaderSection(THeaderStrings(FSections).FList[X])^.Width
  1767.   else
  1768.     Result := 0;
  1769. end;
  1770.  
  1771. procedure THeader.SetWidth(X: Integer; Value: Integer);
  1772. begin
  1773.   if X < 0 then Exit;
  1774.   PHeaderSection(THeaderStrings(FSections).FList[X])^.Width := Value;
  1775.   Invalidate;
  1776. end;
  1777.  
  1778. procedure THeader.WMNCHitTest(var Msg: TWMNCHitTest);
  1779. begin
  1780.   inherited;
  1781.   FHitTest := SmallPointToPoint(Msg.Pos);
  1782. end;
  1783.  
  1784. procedure THeader.WMSetCursor(var Msg: TWMSetCursor);
  1785. var
  1786.   Cur: HCURSOR;
  1787.   I: Integer;
  1788.   X: Integer;
  1789. begin
  1790.   Cur := 0;
  1791.   FResizeSection := 0;
  1792.   FHitTest := ScreenToClient(FHitTest);
  1793.   X := 2;
  1794.   with Msg do
  1795.     if HitTest = HTCLIENT then
  1796.       for I := 0 to FSections.Count - 2 do  { don't count last section }
  1797.       begin
  1798.         Inc(X, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1799.         FMouseOffset := X - (FHitTest.X + 2);
  1800.         if Abs(FMouseOffset) < 4 then
  1801.         begin
  1802.           Cur := LoadCursor(0, IDC_SIZEWE);
  1803.           FResizeSection := I;
  1804.           Break;
  1805.         end;
  1806.       end;
  1807.   FCanResize := (FAllowResize or (csDesigning in ComponentState)) and (Cur <> 0);
  1808.   if FCanResize then SetCursor(Cur)
  1809.   else inherited;
  1810. end;
  1811.  
  1812. procedure THeader.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1813.   X, Y: Integer);
  1814. begin
  1815.   inherited MouseDown(Button, Shift, X, Y);
  1816.   if ((csDesigning in ComponentState) and (Button = mbRight)) or (Button = mbLeft) then
  1817.     if FCanResize then SetCapture(Handle);
  1818. end;
  1819.  
  1820. procedure THeader.MouseMove(Shift: TShiftState; X, Y: Integer);
  1821. var
  1822.   I: Integer;
  1823.   AbsPos: Integer;
  1824.   MinPos: Integer;
  1825.   MaxPos: Integer;
  1826. begin
  1827.   inherited MouseMove(Shift, X, Y);
  1828.   if (GetCapture = Handle) and FCanResize then
  1829.   begin
  1830.     { absolute position of this item }
  1831.     AbsPos := 2;
  1832.     for I := 0 to FResizeSection do
  1833.       Inc(AbsPos, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1834.  
  1835.     if FResizeSection > 0 then MinPos := AbsPos -
  1836.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width + 2
  1837.     else MinPos := 2;
  1838.     MaxPos := ClientWidth - 2;
  1839.     if X < MinPos then X := MinPos;
  1840.     if X > MaxPos then X := MaxPos;
  1841.  
  1842.     Dec(PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width,
  1843.       (AbsPos - X - 2) - FMouseOffset);
  1844.     Sizing(FResizeSection,
  1845.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width);
  1846.     Refresh;
  1847.   end;
  1848. end;
  1849.  
  1850. procedure THeader.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1851.   X, Y: Integer);
  1852. begin
  1853.   if FCanResize then
  1854.   begin
  1855.     ReleaseCapture;
  1856.     Sized(FResizeSection,
  1857.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width);
  1858.     FCanResize := False;
  1859.   end;
  1860.   inherited MouseUp(Button, Shift, X, Y);
  1861. end;
  1862.  
  1863. procedure THeader.Sizing(ASection, AWidth: Integer);
  1864. begin
  1865.   if Assigned(FOnSizing) then FOnSizing(Self, ASection, AWidth);
  1866. end;
  1867.  
  1868. procedure THeader.Sized(ASection, AWidth: Integer);
  1869. var
  1870.   Form: TCustomForm;
  1871. begin
  1872.   if Assigned(FOnSized) then FOnSized(Self, ASection, AWidth);
  1873.   if csDesigning in ComponentState then
  1874.   begin
  1875.     Form := GetParentForm(Self);
  1876.     if Form <> nil then
  1877.       Form.Designer.Modified;
  1878.   end;
  1879. end;
  1880.  
  1881. { TGroupButton }
  1882.  
  1883. type
  1884.   TGroupButton = class(TRadioButton)
  1885.   private
  1886.     FInClick: Boolean;
  1887.     procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
  1888.   protected
  1889.     procedure ChangeScale(M, D: Integer); override;
  1890.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  1891.     procedure KeyPress(var Key: Char); override;
  1892.   public
  1893.     constructor InternalCreate(RadioGroup: TCustomRadioGroup);
  1894.     destructor Destroy; override;
  1895.   end;
  1896.  
  1897. constructor TGroupButton.InternalCreate(RadioGroup: TCustomRadioGroup);
  1898. begin
  1899.   inherited Create(RadioGroup);
  1900.   RadioGroup.FButtons.Add(Self);
  1901.   Visible := False;
  1902.   Enabled := RadioGroup.Enabled;
  1903.   ParentShowHint := False;
  1904.   OnClick := RadioGroup.ButtonClick;
  1905.   Parent := RadioGroup;
  1906. end;
  1907.  
  1908. destructor TGroupButton.Destroy;
  1909. begin
  1910.   TCustomRadioGroup(Owner).FButtons.Remove(Self);
  1911.   inherited Destroy;
  1912. end;
  1913.  
  1914. procedure TGroupButton.CNCommand(var Message: TWMCommand);
  1915. begin
  1916.   if not FInClick then
  1917.   begin
  1918.     FInClick := True;
  1919.     try
  1920.       if ((Message.NotifyCode = BN_CLICKED) or
  1921.         (Message.NotifyCode = BN_DOUBLECLICKED)) and
  1922.         TCustomRadioGroup(Parent).CanModify then
  1923.         inherited;
  1924.     except
  1925.       Application.HandleException(Self);
  1926.     end;
  1927.     FInClick := False;
  1928.   end;
  1929. end;
  1930.  
  1931. procedure TGroupButton.ChangeScale(M, D: Integer);
  1932. begin
  1933. end;
  1934.  
  1935. procedure TGroupButton.KeyPress(var Key: Char);
  1936. begin
  1937.   inherited KeyPress(Key);
  1938.   TCustomRadioGroup(Parent).KeyPress(Key);
  1939.   if (Key = #8) or (Key = ' ') then
  1940.   begin
  1941.     if not TCustomRadioGroup(Parent).CanModify then Key := #0;
  1942.   end;
  1943. end;
  1944.  
  1945. procedure TGroupButton.KeyDown(var Key: Word; Shift: TShiftState);
  1946. begin
  1947.   inherited KeyDown(Key, Shift);
  1948.   TCustomRadioGroup(Parent).KeyDown(Key, Shift);
  1949. end;
  1950.  
  1951. { TCustomRadioGroup }
  1952.  
  1953. constructor TCustomRadioGroup.Create(AOwner: TComponent);
  1954. begin
  1955.   inherited Create(AOwner);
  1956.   ControlStyle := [csSetCaption, csDoubleClicks];
  1957.   FButtons := TList.Create;
  1958.   FItems := TStringList.Create;
  1959.   TStringList(FItems).OnChange := ItemsChange;
  1960.   FItemIndex := -1;
  1961.   FColumns := 1;
  1962. end;
  1963.  
  1964. destructor TCustomRadioGroup.Destroy;
  1965. begin
  1966.   SetButtonCount(0);
  1967.   TStringList(FItems).OnChange := nil;
  1968.   FItems.Free;
  1969.   FButtons.Free;
  1970.   inherited Destroy;
  1971. end;
  1972.  
  1973. procedure TCustomRadioGroup.ArrangeButtons;
  1974. var
  1975.   ButtonsPerCol, ButtonWidth, ButtonHeight, TopMargin, I: Integer;
  1976.   DC: HDC;
  1977.   SaveFont: HFont;
  1978.   Metrics: TTextMetric;
  1979.   DeferHandle: THandle;
  1980. begin
  1981.   if (FButtons.Count <> 0) and not FReading then
  1982.   begin
  1983.     DC := GetDC(0);
  1984.     SaveFont := SelectObject(DC, Font.Handle);
  1985.     GetTextMetrics(DC, Metrics);
  1986.     SelectObject(DC, SaveFont);
  1987.     ReleaseDC(0, DC);
  1988.     ButtonsPerCol := (FButtons.Count + FColumns - 1) div FColumns;
  1989.     ButtonWidth := (Width - 10) div FColumns;
  1990.     I := Height - Metrics.tmHeight - 5;
  1991.     ButtonHeight := I div ButtonsPerCol;
  1992.     TopMargin := Metrics.tmHeight + 1 + (I mod ButtonsPerCol) div 2;
  1993.     DeferHandle := BeginDeferWindowPos(FButtons.Count);
  1994.     for I := 0 to FButtons.Count - 1 do
  1995.       with TGroupButton(FButtons[I]) do
  1996.       begin
  1997.         DeferHandle := DeferWindowPos(DeferHandle, Handle, 0,
  1998.           (I div ButtonsPerCol) * ButtonWidth + 8,
  1999.           (I mod ButtonsPerCol) * ButtonHeight + TopMargin,
  2000.           ButtonWidth, ButtonHeight,
  2001.           SWP_NOZORDER or SWP_NOACTIVATE);
  2002.         Visible := True;
  2003.       end;
  2004.     EndDeferWindowPos(DeferHandle);
  2005.   end;
  2006. end;
  2007.  
  2008. procedure TCustomRadioGroup.ButtonClick(Sender: TObject);
  2009. begin
  2010.   if not FUpdating then
  2011.   begin
  2012.     FItemIndex := FButtons.IndexOf(Sender);
  2013.     Changed;
  2014.     Click;
  2015.   end;
  2016. end;
  2017.  
  2018. procedure TCustomRadioGroup.ItemsChange(Sender: TObject);
  2019. begin
  2020.   if not FReading then
  2021.   begin
  2022.     if FItemIndex >= FItems.Count then FItemIndex := FItems.Count - 1;
  2023.     UpdateButtons;
  2024.   end;
  2025. end;
  2026.  
  2027. procedure TCustomRadioGroup.ReadState(Reader: TReader);
  2028. begin
  2029.   FReading := True;
  2030.   inherited ReadState(Reader);
  2031.   FReading := False;
  2032.   UpdateButtons;
  2033. end;
  2034.  
  2035. procedure TCustomRadioGroup.SetButtonCount(Value: Integer);
  2036. begin
  2037.   while FButtons.Count < Value do TGroupButton.InternalCreate(Self);
  2038.   while FButtons.Count > Value do TGroupButton(FButtons.Last).Free;
  2039. end;
  2040.  
  2041. procedure TCustomRadioGroup.SetColumns(Value: Integer);
  2042. begin
  2043.   if Value < 1 then Value := 1;
  2044.   if Value > 16 then Value := 16;
  2045.   if FColumns <> Value then
  2046.   begin
  2047.     FColumns := Value;
  2048.     ArrangeButtons;
  2049.   end;
  2050. end;
  2051.  
  2052. procedure TCustomRadioGroup.SetItemIndex(Value: Integer);
  2053. begin
  2054.   if FReading then FItemIndex := Value else
  2055.   begin
  2056.     if Value < -1 then Value := -1;
  2057.     if Value >= FButtons.Count then Value := FButtons.Count - 1;
  2058.     if FItemIndex <> Value then
  2059.     begin
  2060.       if FItemIndex >= 0 then
  2061.         TGroupButton(FButtons[FItemIndex]).Checked := False;
  2062.       FItemIndex := Value;
  2063.       if FItemIndex >= 0 then
  2064.         TGroupButton(FButtons[FItemIndex]).Checked := True;
  2065.     end;
  2066.   end;
  2067. end;
  2068.  
  2069. procedure TCustomRadioGroup.SetItems(Value: TStrings);
  2070. begin
  2071.   FItems.Assign(Value);
  2072. end;
  2073.  
  2074. procedure TCustomRadioGroup.UpdateButtons;
  2075. var
  2076.   I: Integer;
  2077. begin
  2078.   SetButtonCount(FItems.Count);
  2079.   for I := 0 to FButtons.Count - 1 do
  2080.     TGroupButton(FButtons[I]).Caption := FItems[I];
  2081.   if FItemIndex >= 0 then
  2082.   begin
  2083.     FUpdating := True;
  2084.     TGroupButton(FButtons[FItemIndex]).Checked := True;
  2085.     FUpdating := False;
  2086.   end;
  2087.   ArrangeButtons;
  2088.   Invalidate;
  2089. end;
  2090.  
  2091. procedure TCustomRadioGroup.CMEnabledChanged(var Message: TMessage);
  2092. var
  2093.   I: Integer;
  2094. begin
  2095.   inherited;
  2096.   for I := 0 to FButtons.Count - 1 do
  2097.     TGroupButton(FButtons[I]).Enabled := Enabled;
  2098. end;
  2099.  
  2100. procedure TCustomRadioGroup.CMFontChanged(var Message: TMessage);
  2101. begin
  2102.   inherited;
  2103.   ArrangeButtons;
  2104. end;
  2105.  
  2106. procedure TCustomRadioGroup.WMSize(var Message: TWMSize);
  2107. begin
  2108.   inherited;
  2109.   ArrangeButtons;
  2110. end;
  2111.  
  2112. function TCustomRadioGroup.CanModify: Boolean;
  2113. begin
  2114.   Result := True;
  2115. end;
  2116.  
  2117. procedure TCustomRadioGroup.GetChildren(Proc: TGetChildProc; Root: TComponent);
  2118. begin
  2119. end;
  2120.  
  2121. type
  2122.   THack = class(TWinControl);
  2123.  
  2124. { TSplitter }  
  2125.  
  2126. constructor TSplitter.Create(AOwner: TComponent);
  2127. begin
  2128.   inherited Create(AOwner);
  2129.   Align := alLeft;
  2130.   Width := 3;
  2131.   Cursor := crHSplit;
  2132.   FMinSize := 30;
  2133.   FBeveled := True;
  2134. end;
  2135.  
  2136. procedure TSplitter.AllocateLineDC;
  2137. begin
  2138.   FLineDC := GetDCEx(Parent.Handle, 0, DCX_CACHE or DCX_CLIPSIBLINGS
  2139.     or DCX_LOCKWINDOWUPDATE);
  2140. end;
  2141.  
  2142. procedure TSplitter.DrawLine;
  2143. var
  2144.   P: TPoint;
  2145. begin
  2146.   FLineVisible := not FLineVisible;
  2147.   P := Point(Left, Top);
  2148.   if Align in [alLeft, alRight] then
  2149.     P.X := Left + FSplit else
  2150.     P.Y := Top + FSplit;
  2151.   with P do PatBlt(FLineDC, X, Y, Width, Height, PATINVERT);
  2152. end;
  2153.  
  2154. procedure TSplitter.ReleaseLineDC;
  2155. begin
  2156.   ReleaseDC(Parent.Handle, FLineDC);
  2157. end;
  2158.  
  2159. procedure TSplitter.Paint;
  2160. var
  2161.   FrameBrush: HBRUSH;
  2162.   R: TRect;
  2163. begin
  2164.   R := ClientRect;
  2165.   Canvas.Brush.Color := Color;
  2166.   Canvas.FillRect(ClientRect);
  2167.   if Beveled then
  2168.   begin
  2169.     if Align in [alLeft, alRight] then
  2170.       InflateRect(R, -1, 2) else
  2171.       InflateRect(R, 2, -1);
  2172.     OffsetRect(R, 1, 1);
  2173.     FrameBrush := CreateSolidBrush(ColorToRGB(clBtnHighlight));
  2174.     FrameRect(Canvas.Handle, R, FrameBrush);
  2175.     DeleteObject(FrameBrush);
  2176.     OffsetRect(R, -2, -2);
  2177.     FrameBrush := CreateSolidBrush(ColorToRGB(clBtnShadow));
  2178.     FrameRect(Canvas.Handle, R, FrameBrush);
  2179.     DeleteObject(FrameBrush);
  2180.   end;
  2181. end;
  2182.  
  2183. procedure TSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState;
  2184.   X, Y: Integer);
  2185.  
  2186.   function FindControl: TControl;
  2187.   var
  2188.     P: TPoint;
  2189.     I: Integer;
  2190.   begin
  2191.     Result := nil;
  2192.     P := Point(Left, Top);
  2193.     case Align of
  2194.       alLeft: Dec(P.X);
  2195.       alRight: Inc(P.X, Width);
  2196.       alTop: Dec(P.Y);
  2197.       alBottom: Inc(P.Y, Height);
  2198.     else
  2199.       Exit;
  2200.     end;
  2201.     for I := 0 to Parent.ControlCount - 1 do
  2202.     begin
  2203.       Result := Parent.Controls[I];
  2204.       if PtInRect(Result.BoundsRect, P) then Exit;
  2205.     end;
  2206.     Result := nil;
  2207.   end;
  2208.  
  2209. var
  2210.   I: Integer;
  2211. begin
  2212.   inherited;
  2213.   if Button = mbLeft then
  2214.   begin
  2215.     FControl := FindControl;
  2216.     FDownPos := Point(X, Y);
  2217.     if Assigned(FControl) then
  2218.     begin
  2219.       if Align in [alLeft, alRight] then
  2220.       begin
  2221.         FMaxSize := Parent.ClientWidth - FMinSize;
  2222.         for I := 0 to Parent.ControlCount - 1 do
  2223.           with Parent.Controls[I] do
  2224.             if Align in [alLeft, alRight] then Dec(FMaxSize, Width);
  2225.         Inc(FMaxSize, FControl.Width);
  2226.       end
  2227.       else
  2228.       begin
  2229.         FMaxSize := Parent.ClientHeight - FMinSize;
  2230.         for I := 0 to Parent.ControlCount - 1 do
  2231.           with Parent.Controls[I] do
  2232.             if Align in [alTop, alBottom] then Dec(FMaxSize, Height);
  2233.         Inc(FMaxSize, FControl.Height);
  2234.       end;
  2235.       UpdateSize(X, Y);
  2236.       AllocateLineDC;
  2237.       with ValidParentForm(Self) do
  2238.         if ActiveControl <> nil then
  2239.         begin
  2240.           FActiveControl := ActiveControl;
  2241.           FOldKeyDown := THack(FActiveControl).OnKeyDown;
  2242.           THack(FActiveControl).OnKeyDown := FocusKeyDown;
  2243.         end;
  2244.       DrawLine;
  2245.     end;
  2246.   end;
  2247. end;
  2248.  
  2249. procedure TSplitter.UpdateSize(X, Y: Integer);
  2250. var
  2251.   S: Integer;
  2252. begin
  2253.   if Align in [alLeft, alRight] then
  2254.     FSplit := X - FDownPos.X
  2255.   else
  2256.     FSplit := Y - FDownPos.Y;
  2257.   S := 0;
  2258.   case Align of
  2259.     alLeft: S := FControl.Width + FSplit;
  2260.     alRight: S := FControl.Width - FSplit;
  2261.     alTop: S := FControl.Height + FSplit;
  2262.     alBottom: S := FControl.Height - FSplit;
  2263.   end;
  2264.   FNewSize := S;
  2265.   if S < FMinSize then
  2266.     FNewSize := FMinSize
  2267.   else if S > FMaxSize then
  2268.     FNewSize := FMaxSize;
  2269.   if S <> FNewSize then
  2270.   begin
  2271.     if Align in [alRight, alBottom] then
  2272.       S := S - FNewSize else
  2273.       S := FNewSize - S;
  2274.     Inc(FSplit, S);
  2275.   end;
  2276. end;
  2277.  
  2278. procedure TSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
  2279. begin
  2280.   inherited;
  2281.   if Assigned(FControl) then
  2282.   begin
  2283.     DrawLine;
  2284.     UpdateSize(X, Y);
  2285.     DrawLine;
  2286.   end;
  2287. end;
  2288.  
  2289. procedure TSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState;
  2290.   X, Y: Integer);
  2291. begin
  2292.   inherited;
  2293.   if Assigned(FControl) then
  2294.   begin
  2295.     DrawLine;
  2296.     case Align of
  2297.       alLeft: FControl.Width := FNewSize;
  2298.       alTop: FControl.Height := FNewSize;
  2299.       alRight:
  2300.         begin
  2301.           Parent.DisableAlign;
  2302.           try
  2303.             FControl.Left := FControl.Left + (FControl.Width - FNewSize);
  2304.             FControl.Width := FNewSize;
  2305.           finally
  2306.             Parent.EnableAlign;
  2307.           end;
  2308.         end;
  2309.       alBottom:
  2310.         begin
  2311.           Parent.DisableAlign;
  2312.           try
  2313.             FControl.Top := FControl.Top + (FControl.Height - FNewSize);
  2314.             FControl.Height := FNewSize;
  2315.           finally
  2316.             Parent.EnableAlign;
  2317.           end;
  2318.         end;
  2319.     end;
  2320.     StopSizing;
  2321.   end;
  2322. end;
  2323.  
  2324. procedure TSplitter.FocusKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  2325. begin
  2326.   if Key = VK_ESCAPE then
  2327.     StopSizing
  2328.   else if Assigned(FOldKeyDown) then
  2329.     FOldKeyDown(Sender, Key, Shift);
  2330. end;
  2331.  
  2332. procedure TSplitter.SetBeveled(Value: Boolean);
  2333. begin
  2334.   FBeveled := Value;
  2335.   Repaint;
  2336. end;
  2337.  
  2338. procedure TSplitter.StopSizing;
  2339. begin
  2340.   if Assigned(FControl) then
  2341.   begin
  2342.     if FLineVisible then DrawLine;
  2343.     FControl := nil;
  2344.     ReleaseLineDC;
  2345.     if Assigned(FActiveControl) then
  2346.     begin
  2347.       THack(FActiveControl).OnKeyDown := FOldKeyDown;
  2348.       FActiveControl := nil;
  2349.     end;
  2350.   end;
  2351.   if Assigned(FOnMoved) then
  2352.     FOnMoved(Self);
  2353. end;
  2354.  
  2355. end.
  2356.